﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace Eff.Utils.Attributes
{
    /// <summary>
    /// 用于扩展在字段上附加属性
    /// http://www.cnblogs.com/JeffreyZhao/archive/2009/01/07/1371059.html
    /// todo：添加获取列表的扩展方法，添加缓存设置
    ///
    /// </summary>
    [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
    public class AttachDataAttribute : Attribute
    {
        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public AttachDataAttribute(object key, object value)
        {
            Key = key;
            Value = value;
        }

        /// <summary>
        /// 默认text文本的的key
        /// </summary>
        /// <param name="value"></param>
        public AttachDataAttribute(object value)
        {
            Key = AttachDataKeyType.DefaultText;
            Value = value;
        }
        /// <summary>
        /// 键
        ///  </summary>
        public object Key { get; private set; }

        /// <summary>
        /// 值
        /// </summary>
        public object Value { get; private set; }

    }

    /// <summary>
    /// AttachDataAttribute中key类型
    /// </summary>
    public enum AttachDataKeyType
    {
        /// <summary>
        /// 默认值
        /// </summary>
        DefaultText = 0
    }
    /// <summary>
    /// 扩展方法
    /// </summary>
    public static class AttachDataExtensions
    {
        /// <summary>
        /// 获取附加属性
        /// </summary>
        /// <param name="provider"></param>
        /// <param name="key">附加属性值,不填或为null获取默认附加值</param>
        /// <returns></returns>
        public static object GetAttachedData(this ICustomAttributeProvider provider, object key = null)
        {
            key = GetKey(key);
            var attributes = (AttachDataAttribute[])provider.GetCustomAttributes(typeof(AttachDataAttribute), false);
            return attributes.First(a => a.Key.Equals(key)).Value;
        }

        /// <summary>
        /// 获取附加属性
        /// </summary>
        /// <typeparam name="T">返回类型</typeparam>
        /// <param name="provider"></param>
        /// <param name="key">附加属性值,不填或为null获取默认附加值</param>
        /// <returns></returns>
        public static T GetAttachedData<T>(this ICustomAttributeProvider provider, object key = null)
        {
            key = GetKey(key);
            return (T)provider.GetAttachedData(key);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="provider"></param>
        /// <returns></returns>
        public static Dictionary<object, object> GetAllAttachedData(this ICustomAttributeProvider provider)
        {
            var attributes = (AttachDataAttribute[])provider.GetCustomAttributes(typeof(AttachDataAttribute), false);
            return attributes.ToDictionary(t => t.Key, t => t.Value);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="provider"></param>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <returns></returns>
        public static Dictionary<TKey, TValue> GetAllAttachedData<TKey, TValue>(this ICustomAttributeProvider provider)
        {
            var attributes = (AttachDataAttribute[])provider.GetCustomAttributes(typeof(AttachDataAttribute), false);
            return attributes.ToDictionary(t => (TKey)t.Key, t => (TValue)t.Value);
        }
        /// <summary>
        /// 获取枚举附加属性
        /// </summary>
        /// <param name="value">枚举值</param>
        /// <param name="key">附加属性值,不填或为null获取默认附加值</param>
        /// <returns></returns>
        public static object GetAttachedData(this Enum value, object key = null)
        {
            key = GetKey(key);
            return value.GetType().GetField(value.ToString()).GetAttachedData(key);
        }

        private static object GetKey(object key)
        {
            return key ?? AttachDataKeyType.DefaultText;
        }
        /// <summary>
        /// 获取附加属性
        /// </summary>
        /// <param name="value">枚举值</param>
        /// <param name="key">附加属性值</param>
        /// <typeparam name="T">返回类型</typeparam>
        /// <returns></returns>
        public static T GetAttachedData<T>(this Enum value, object key = null)
        {
            return (T)value.GetAttachedData(key);
        }


        /// <summary>
        /// 
        /// </summary>
        /// <param name="value"></param>
        /// <typeparam name="TKey"></typeparam>
        /// <typeparam name="TValue"></typeparam>
        /// <returns></returns>
        public static Dictionary<TKey, TValue> GetAllAttachedData<TKey, TValue>(this Enum value)
        {
            return value.GetType().GetField(value.ToString()).GetAllAttachedData<TKey, TValue>();
        }
        //        public static Dictionary<TKey, TValue> GetDic<TKey, TValue, TClassType>(TClassType classType)
        //        {
        //
        //        }
    }
}
